package cn.zyl.demo.common.boot.controller;

import cn.zyl.demo.common.boot.annotation.MethodHandleBoot;
import cn.zyl.demo.common.boot.beans.CommonApiBean;
import cn.zyl.demo.common.boot.beans.ResBody;
import cn.zyl.demo.common.boot.enums.ResCodeEnum;
import cn.zyl.demo.common.boot.tools.ResBodyTool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * BootBaseController类说明: 请求接口公共部分
 *
 * @author wsz
 * @version v1.0
 * @date 2020-08-03
 */
public abstract class BaseBootController {
    private static final Logger LOGGER = LoggerFactory.getLogger(BaseBootController.class);
    private static final String HELLO = " Hello Spring Boot !";
    @Autowired
    private WebApplicationContext context;
    /**
     * Web应用程序提供配置。 这是只读的，而在应用程序运行，但如果实现支持，这可能被重新加载
     * @return web上下文
     */
    public WebApplicationContext getContext() { return context; }

    /**
     * ping请求，返回200状态
     * @return 成功状态
     */
    @RequestMapping("ping")
    public int ping(){ return ResCodeEnum.SUCCESS.getCode(); }
    /**
     * 请求根路径
     * @return 字符串
     */
    @RequestMapping("")
    public String index(){ return getModelName()+HELLO; }
    /**
     * 名称
     * @return 成功状态
     */
    @RequestMapping("name")
    public ResBody<String> name() { return ResBodyTool.success(getModelName()); }
    /**
     * 运行状态
     * @return 当前模块运行状态
     */
    public abstract ResBody<String> info();

    /**
     * 当前模块名称
     * @return 名称
     */
    protected abstract String getModelName();
    /**
     * 获取项目的接口请求信息
     * @return 接口信息列表
     */
    @RequestMapping("api")
    @MethodHandleBoot("获取项目的API")
    public ResBody<List<CommonApiBean>> api(){
        LOGGER.info("api--start--");
        // 获取spring mvc处理器映射器组件对象 RequestMappingHandlerMapping无法直接注入
        RequestMappingHandlerMapping mapping = context.getBean(RequestMappingHandlerMapping.class);
        // 获取url与类和方法的对应信息
        Map<RequestMappingInfo, HandlerMethod> map=mapping.getHandlerMethods();
        List<CommonApiBean> apiBeanList = new ArrayList<>(map.size());
        // 返回信息
        CommonApiBean apiBean;
        //请求映射信息
        RequestMappingInfo info;
        //请求相关方法和bean
        Method method;
        for (Map.Entry<RequestMappingInfo,HandlerMethod> entry: map.entrySet()) {
            info = entry.getKey();
            //请求相关方法和bean
            method = entry.getValue().getMethod();
            //获取请求url
            StringBuilder url = new StringBuilder();
            if(!info.getPatternsCondition().isEmpty() && !info.getPatternsCondition().getPatterns().isEmpty()){
                boolean boo = info.getPatternsCondition().getPatterns().size() == 1;
                info.getPatternsCondition().getPatterns().forEach(u-> url.append(u).append(boo?"":","));
            }
            //获取请求的方式列表
            StringBuilder type = new StringBuilder();
            if(!info.getMethodsCondition().isEmpty() && !info.getMethodsCondition().getMethods().isEmpty()){
                boolean boo = info.getMethodsCondition().getMethods().size() == 1;
                info.getMethodsCondition().getMethods().forEach(m-> type.append(m).append(boo?"":","));
            }
            apiBean = new CommonApiBean(url.toString(), method, type.toString());
            apiBeanList.add(apiBean);
        }
        LOGGER.info("api--end--");
        return ResBodyTool.success(apiBeanList);
    }
}
